package com.liuning.graduationdemo.component;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

//websocket服务(双通道连接)
@ServerEndpoint(value = "/videoImserver/{username}")
@Component
public class VideoWebSocketServer {

    //打印连接日志消息
    private static final Logger log = LoggerFactory.getLogger(VideoWebSocketServer.class);

    //记录当前在线的连接数
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 连接建立成功时调用的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessionMap.put(username,session);
        log.info("有新用户加入 username={}，当前在线人数为：{}",username,sessionMap.size());

        JSONObject result = new JSONObject();
        JSONArray array = new JSONArray();
        result.set("users",array);
        for (Object key : sessionMap.keySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("username",key);
            array.add(jsonObject);
        }
        //最后组装成的格式：   {"users":[{"username":"lihua"},{"username":"admin"}]}
        //后台给所有的客户端发送消息
        sendAllMessage(JSONUtil.toJsonStr(result));
    }

    /**
     * 连接关闭时调用的方法
     * @param session
     * @param username
     */
    @OnClose
    public void onClosed(Session session,@PathParam("username") String username) {
        sessionMap.remove(username);
        log.info("有一连接关闭，移除 username={} 的用户session，当前在线人数为：{}",username,sessionMap.size());
    }

    /**
     * 后台收到客户端发送过来的消息
     * onMessage是一个消息的中转站
     * 接收前端socket.send(JSON.stringify(message))发送过来的json数据
     * {"from":"zhangsan","to":"admin","text":"聊天文本"}
     * @param message
     * @param session
     * @param username
     */
    @OnMessage
    public void onMessage(String message,Session session,@PathParam("username") String username) {
        System.out.println("服务器收到的message：" + message);
        log.info("服务端收到用户username={} 的消息：{}",username,message);
        JSONObject obj = JSONUtil.parseObj(message);

        String toUsername = null;
        //event 表示发送的类型是offer还是answer
        String event = obj.getStr("event");
        //data表示发送的具体内容
        String data = obj.getStr("data");
        if (!event.equals("_ice_candidate")) {
            //to 表示发送给哪个用户，比如某某某发送给admin用户
            toUsername = obj.getStr("toUser");
        }

        //确认消息的发起者
        String fromUser;
        //服务器端重新组装消息，组装之后的消息包含发送人和发送的文本内容
        JSONObject jsonObject = new JSONObject();

        //第一步：消息内容是视频前用于确定对方是否同意
        if (event.equals("confirm") || event.equals("refuse") || event.equals("agree")) {
            fromUser = obj.getStr("fromUser");
            jsonObject.set("event",event);
            jsonObject.set("data",data);
            jsonObject.set("fromUser",fromUser);
            log.info("视频通话确认消息");
            sendMessage(jsonObject.toString(),sessionMap.get(toUsername));
        } else if (event.equals("_offer") || event.equals("_answer")) {
            fromUser = obj.getStr("fromUser");
            jsonObject.set("event",event);
            jsonObject.set("data",data);
            jsonObject.set("fromUser",fromUser);
            log.info("发送offer和answer消息");
            sendMessage(message,sessionMap.get(toUsername));
        }else if (event.equals("_ice_candidate")) {
//            fromUser = obj.getStr("fromUser");
//            jsonObject.set("event",event);
//            jsonObject.set("data",data);
//            jsonObject.set("fromUser",fromUser);
            log.info("发送icecandidate消息");
//            sendMessage(message,sessionMap.get(toUsername));
            sendAllMessage(message);
        }
        Session toSession = null;
        if (toUsername != null) {
            //根据toUsername来获取session，再通过session发送消息文本
            toSession = sessionMap.get(toUsername);
        }
        if (toSession != null) {

//            this.sendMessage(jsonObject.toString(),toSession);
            log.info("发送给用户 username={}，消息：{}",toUsername,jsonObject.toString());
//            this.sendMessage(obj.toString(),toSession);
//            log.info("发送给用户 username={}，消息：{}",toUsername,obj.toString());
        }else {
            log.info("发送失败，未找到用户username={} 的session",toUsername);
        }
    }

    @OnError
    public void onError(Session session,Throwable error) {
        log.error("聊天发生错误");
        error.printStackTrace();
    }

    /**
     * 服务端发送消息给客户端
     * @param message 发送的消息内容
     * @param toSession 接收者的session
     */
    private void sendMessage(String message, Session toSession) {
        try {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }

    /**
     * 服务端给所有客户端发消息
     * @param message 发送的消息内容
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()) {
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }

}
